#include "head.h"


//******************** hash_map相关 *****************

static uint32_t hash(const void* key, int len, uint32_t seed);
static int make_hash_map_big_again(hash_map_t* hash_map);

int hash_map_init(hash_map_t* hash_map, int size){
    hash_map->size = 0;
    hash_map->capacity = size;
    hash_map->seed = 131;
    // 申请对应个数的hash_node的堆空间
    hash_map->map = (hash_node_t**)calloc(hash_map->capacity, sizeof(hash_node_t*));
    
    
    return 0;
}

int hash_map_add(hash_map_t* hash_map, int net_fd, int index){

    if(hash_map->size > (hash_map->capacity*0.7)){
        // 扩容
        make_hash_map_big_again(hash_map);
    }
    // 计算net_fd的hash值，得到hash表的下标
    int hash_idx = hash(&net_fd, sizeof(net_fd),hash_map->seed) % (hash_map->capacity);
    // 创建新的结点， 然后头插法
    hash_node_t* new_node = (hash_node_t*)calloc(1,sizeof(hash_node_t));
    new_node->index = index;
    new_node->net_fd = net_fd;
    // 头插法
    new_node->next = hash_map->map[hash_idx];
    hash_map->map[hash_idx] = new_node;

    hash_map->size++;
    //printf("hash_map->size = %d\n", hash_map->size); 

    return 0;

}

int hash_map_del(hash_map_t* hash_map, int net_fd, int* index){
    int hash_idx = hash(&net_fd, sizeof(net_fd),hash_map->seed) % (hash_map->capacity);
    hash_node_t* pre = NULL;
    hash_node_t* cur = hash_map->map[hash_idx];
    while(cur != NULL){
        if(cur->net_fd == net_fd){
            if(pre == NULL){
                hash_map->map[hash_idx] = cur->next;
                hash_map->size--; 
            }
            else{
                pre->next = cur->next;
                hash_map->size--; 
            }
            //printf("hash_map->size = %d\n", hash_map->size); 
            *index = cur->index;
            free(cur);
            return 0;
        }
        pre = cur;
        cur = cur->next;       
    }
    return -1;

}



static uint32_t hash(const void* key, int len, uint32_t seed) {
    const uint32_t m = 0x5bd1e995;
    const int r = 24;
    uint32_t h = seed ^ len;
    const unsigned char* data = (const unsigned char*)key;

    while (len >= 4) {
        uint32_t k = *(uint32_t*)data;
        k *= m;
        k ^= k >> r;
        k *= m;
        h *= m;
        h ^= k;
        data += 4;
        len -= 4;
    }

    switch (len) {
        case 3: h ^= data[2] << 16;
        case 2: h ^= data[1] << 8;
        case 1: h ^= data[0];
            h *= m;
    };

    h ^= h >> 13;
    h *= m;
    h ^= h >> 15;

    return h;
}

static int make_hash_map_big_again(hash_map_t* hash_map){
    int new_capacity = (hash_map->capacity)*2;
    hash_node_t** new_map = (hash_node_t**)calloc(new_capacity, sizeof(hash_node_t*));

    
    for(int i=0; i<hash_map->capacity; i++){
        while(hash_map->map[i] != NULL){
            // 保存下个结点的指针
            hash_node_t *next = hash_map->map[i]->next;
            
            // 计算结点需要插入的位置，进行头插
            int hash_idx = hash(&(hash_map->map[i]->net_fd), sizeof(hash_map->map[i]->net_fd),hash_map->seed) % (new_capacity);
            hash_map->map[i]->next = new_map[hash_idx];
            new_map[hash_idx] = hash_map->map[i];
            
            // 更新链表结点
            hash_map->map[i] = next;
        }
    }

    // for循环结束，已经将所有结点更新到新的hash表中

    hash_map->capacity = new_capacity;
    free(hash_map->map);
    hash_map->map = new_map;

    return 0;

}

//************************ 超时踢出队列相关 ******************
int timeout_add(timeout_node_t** timeout_queue, int net_fd, int index){
    timeout_node_t* new_node = (timeout_node_t*)calloc(1,sizeof(timeout_node_t));
    // 头插法
    new_node->net_fd = net_fd;
    new_node->next = timeout_queue[index];
    timeout_queue[index] = new_node;

    return 0;
}

int timeout_del(timeout_node_t** timeout_queue, int net_fd, int index){
    timeout_node_t* cur = timeout_queue[index];
    timeout_node_t* pre = NULL;

    while(cur != NULL){
       if(cur->net_fd == net_fd){
          if(pre == NULL){
            timeout_queue[index] = cur->next;
          }
          else{
            pre->next = cur->next;
          }
          free(cur);
          return 0;
       }
       pre = cur;
       cur = cur->next;
    }
    return -1;
}

int timeout_del_index(timeout_node_t** timeout_queue, int index, hash_map_t* hash_map){
    timeout_node_t* cur = timeout_queue[index];
    timeout_queue[index] = NULL;

    while(cur != NULL){
       timeout_node_t* next = cur->next;
       int net_fd = cur->net_fd;
       int num;
       free(cur);
       hash_map_del(hash_map, net_fd, &num); 
       printf("超时踢出 net_fd = %d, index = %d\n",net_fd, num);
       cur = next;
       close(net_fd);
    }
    
    return 0;
}

